#多任务与多线程
#多任务：同一时间进行多个任务
"""
多任务的执行方式：
并发：一个时间段内两个或更多任务交替进行
并行：一个时刻两个或更多任务同时进行
"""
from threading import Thread
from time import sleep

'''
线程：
每一个任务至少有一个线程（主线程）
线程是CPU调度的基本单位
多线程可以完成多任务
'''
import a1
import time
@a1.date_calculater
def test():
    print('现在开始执行test函数')
    time.sleep(2)#将函数的执行挂起2秒，即2秒内不执行
    print('现在停止执行test函数')
#test()
'''
程序运行的开始时间是:9时47分41秒
现在开始执行函数
现在停止执行函数
程序运行的结束时间是:9时47分43秒
程序运行的总时长为:2秒
'''
#再运行一次
#test()
'''
注意到再上一个函数结束运行后，下一个函数才会运行（即使上一个函数被挂起了2秒）
想要同时运行，就要创建多线程
'''
'''
创建多线程：
1.导入模块threading
2.创建Thread（）类、
3.守护线程（主线程结束子线程也会结束）
4.启动子线程start()
5.阻塞主线程join()
'''
import threading
'''
for i in range(4):
    test1=threading.Thread(target=test)
    test1.start()
'''
'''
程序运行的开始时间是:10时49分45秒
现在开始执行函数
程序运行的开始时间是:10时49分45秒
现在开始执行函数
程序运行的开始时间是:10时49分45秒
现在开始执行函数
程序运行的开始时间是:10时49分45秒
现在开始执行函数
现在停止执行函数
程序运行的结束时间是:10时49分47秒
程序运行的总时长为:2秒
现在停止执行函数
现在停止执行函数程序运行的结束时间是:10时49分47秒

程序运行的总时长为:2秒程序运行的结束时间是:10时49分47秒
程序运行的总时长为:2秒

现在停止执行函数
程序运行的结束时间是:10时49分47秒
程序运行的总时长为:2秒
这意味着四个线程是同时进行的
'''
@a1.date_calculater
def test2():
    print('现在开始执行test2函数')
    time.sleep(1)
    print('现在结束执行test2函数')
'''
t1=threading.Thread(target=test)
t2=threading.Thread(target=test2)
t1.start()
t2.start()
print('这是主线程')
'''
'''
test程序运行的开始时间是:11时36分18秒
现在开始执行test函数
test2程序运行的开始时间是:11时36分18秒
这是主线程
现在开始执行test2函数
现在结束执行test2函数
test2程序运行的结束时间是:11时36分19秒
test2程序运行的总时长为:1秒
现在停止执行test函数
test程序运行的结束时间是:11时36分20秒
test程序运行的总时长为:2秒
注意：实际上“这是主线程”语句是随机出现在test2的语法糖和第一条前后的
我们来写一条去掉语法糖的版本，看看会不会有问题
'''
def test3(name):
    print('现在开始执行test3函数,name={}'.format(name))
    sleep(2)
    print('现在停止执行test3函数')
def test4(name):
    print('现在开始执行test4函数,name={}'.format(name))
    sleep(2)
    print('现在停止执行test4函数')
t3=threading.Thread(target=test3,args=('uni',))
t4=threading.Thread(target=test4,args=('uny',))#写成元组的形式才可以传参（不然就变成单线程了）
'''
守护子线程
使用setDaemon守护线程
危险警告：这样写会收到DeprecationWaning的警告，说明setDaemon已经过时辣！
既然如此，我们把它注释掉

t3.setDaemon(True)
t4.setDaemon(True)
但是应该注意到的是，由于守护了线程，主线程并没有结束，所以sleep后面的语句并没有执行
'''

time1=time.time()
t3.start()
t4.start()
print('\n芝士主线程')
time2=time.time()
print('执行时间为{}'.format(time2-time1))
'''
现在开始执行test3函数,name=uni
现在开始执行test4函数,name=uny

芝士主线程
执行时间为0.0016677379608154297
现在停止执行test3函数
现在停止执行test4函数
注：输出仍然是非常奇妙，经常会出现换行符丢失的问题，执行时间不稳定，先结束test3还是先结束test4也时常不同
总之，只有挂起前的输出顺序是稳定的
'''
#线程可以重新命名
t3.setName('线程3')
#有趣的是，setName也过时了（悲）